from Helper import *


def load_data_of_nodes(graph, data, nodes_list):
    """
    输入一个node，查询他的value并且把它放到nodeslist中。
    :param graph:
    :param data:
    :param nodes_list:
    :return:
    """
    single_data = {}
    id_of_nodes = data.identity
    type_of_data = str(data.labels)
    # 查询出入度
    record = list(
        graph.run(
            "MATCH (p" +
            str(type_of_data) +
            ") where id(p)=" +
            str(id_of_nodes) +
            " RETURN size((p)<--()) AS iDegree, size((p)-->()) AS Out_Degree"))

    value = load_value(record[0][0], record[0][1])
    single_data['id'] = id_of_nodes
    single_data['name'] = load_name_of_node(data)
    single_data['category'] = str(data.labels)[1:]
    single_data['property'] = dict(data)
    single_data['property']['value'] = value
    if single_data in nodes_list:
        return
    else:
        nodes_list.append(single_data)
    return nodes_list


def load_data_of_links(link, source_id, destination_id, links_list):
    """
    传入一个links，赋予权重为1，并插入数据库
    :param link: relationship
    :param source_id:
    :param destination_id:
    :param links_list:
    :return:
    """
    single_link_data = {}
    value = 1
    single_link_data['id'] = link.identity
    single_link_data['type'] = load_type_of_link(link)
    single_link_data['property'] = dict(link)
    single_link_data['property']['value'] = value
    single_link_data['source'] = str(source_id)
    single_link_data['target'] = str(destination_id)
    if single_link_data in links_list:
        return
    else:
        links_list.append(single_link_data)
    return links_list


def load_core_data(graph, data_list, nodes_list, links_list):
    for data in data_list:  # 其实只有一层，但是是为了日后万一又TM的变变变，百变小樱吗？
        id_of_data = data[0]
        records_data = list(
            graph.run(
                "match(n)-[r*..1]-(m) where id(n)=" +
                str(id_of_data) +
                " return n,m,r"))
        trans_record_data(graph, records_data, nodes_list, links_list)
        # for record in records_data:
        #     source = record[0]      # source 就是n
        #     destination = record[1]
        #     relationship_list = record[2]
        #     load_data_of_nodes(
        #         graph, source, nodes_list)       # 浪费计算力，但是无所谓了
        #     load_data_of_nodes(graph, destination, nodes_list)
        #     for relationship in relationship_list:
        #         load_data_of_links(
        #             relationship,
        #             source.identity,
        #             destination.identity,
        #             links_list)


def get_accompany_objects_of_ship(graph, object, nodes_list, links_list):
    type_name = str(object.labels)[1:]
    if type_name == "Ship":
        id = object.identity

        query_ship = "MATCH (n:Ship)-[r*..1]-(m:Ship) where id(n)=" + str(id) + " return n,r,m"  # 查询出所有的与这艘船有关的船
        query_ship_data = list(
            graph.run(
                query_ship))
        for record in query_ship_data:
            load_data_of_nodes(graph, record[2], nodes_list)
            for relationship in record[1]:
                load_data_of_links(relationship, record[0].identity, record[2].identity, links_list)

        query_ship_owner = "MATCH (n:Ship)-[r*..1]-(m:Ship_Owner) where id(n)=" + str(
            id) + " return n,r,m"  # 查询出与这艘船有关的Ship_Owner
        query_ship_owner_data = list(
            graph.run(
                query_ship_owner))
        for record in query_ship_owner_data:
            load_data_of_nodes(graph, record[2], nodes_list)
            for relationship in record[1]:
                load_data_of_links(relationship, record[0].identity, record[2].identity, links_list)

        query_country = "MATCH (n:Ship)-[r*..1]-(m:Country) where id(n)=" + str(
            id) + " return n,r,m"  # 查询出与这艘船有关的所 有的Country
        query_country_data = list(
            graph.run(
                query_country))
        for record in query_country_data:
            load_data_of_nodes(graph, record[2], nodes_list)
            for relationship in record[1]:
                load_data_of_links(relationship, record[0].identity, record[2].identity, links_list)
        return 1
    else:
        return 0


def trans_record_data(graph, records_data, nodes_list, links_list):
    """
    查询获取nodes list和links list
    :param graph: 图数据库
    :param records_data: 对某一个Port，与之有关的所有的一级跳点及其关系
    :param nodes_list:待写入的nodes list
    :param links_list:待写入的links list
    :return:None
    """
    ship_count = 0
    for record in records_data:
        # 获取source，就是该id对应的Port
        source = record[0]
        # 获取destination，可能是所有节点
        destination = record[1]

        # 实验发现不限制ship_count也能有理想的数据量
        # if ship_count <= 30:  # 每个港口取出三十艘船，取寻找与之关联的船、公司、归属地的节点和关系
        # ship_count = ship_count + get_accompany_objects(graph, destination, nodes_list, links_list)

        # 假如destination是船，获取与该船有关的所有object，并写入到nodes list和links list中，作为补充数据以丰富可视化
        get_accompany_objects_of_ship(graph, destination, nodes_list, links_list)  # 获取该船相关联的内容。包括与之关联的船、公司、归属地

        # 获取relationship
        relationship_list = record[2]
        # 写入nodes
        load_data_of_nodes(
            graph, source, nodes_list)  # 浪费计算力，但是无所谓了
        load_data_of_nodes(graph, destination, nodes_list)
        # 写入links，使用for是因为两个nodes之间的relationship事list形式。（因为完全可以不是一种关系）
        for relationship in relationship_list:
            load_data_of_links(
                relationship,
                source.identity,
                destination.identity,
                links_list)


def get_all_kind_core_point(
        core_point,
        ship_list,
        country_list,
        port_list,
        ship_owner_list):
    ship_list = ship_list[:core_point]
    ship_owner_list = ship_owner_list[:core_point]
    country_list = country_list[:core_point]
    port_list = port_list[:core_point]
    return [ship_list, country_list, port_list, ship_owner_list]


# <editor-fold desc="获取每一种类型的节点并按照value进行排序">
def get_value_data(data, data_list):
    # data: list[Record]
    # Record record is a list as well
    # use record[0] to get single data, which is a node
    for record in data:
        value = load_value(record[0], record[1])
        if value == 0:  # 权重为0的应当被去掉
            continue
        node0 = record[2]
        id_of_node = node0.identity
        data_list.append((id_of_node, value))
    return data_list.sort(reverse=True, key=take_second)


def get_every_kind_of_nodes_value_data(
        graph,
        ship_list,
        country_list,
        port_list,
        ship_owner_list):
    # GET SHIPS
    records_ship = list(
        graph.run(
            "MATCH (p:Ship) RETURN size((p)<--()) AS "
            "iDegree, size((p)-->()) AS "
            "Out_Degree, "
            "p, "
            "id(p)"))
    get_value_data(records_ship, ship_list)

    # GET Port
    records_port = list(
        graph.run(
            "MATCH (p:Port) RETURN size((p)<--()) AS "
            "iDegree, size((p)-->()) AS "
            "Out_Degree, "
            "p, "
            "id(p)"))
    get_value_data(records_port, port_list)

    # GET Country
    records_country = list(
        graph.run(
            "MATCH (p:Country) RETURN size((p)<--()) AS "
            "iDegree, size((p)-->()) AS "
            "Out_Degree, "
            "p, "
            "id(p)"))
    get_value_data(records_country, country_list)

    # GET ShipOwner
    records_ship_owner = list(
        graph.run(
            "MATCH (p:Ship_Owner) RETURN size((p)<--()) AS "
            "iDegree, size((p)-->()) AS "
            "Out_Degree, "
            "p, "
            "id(p)"))
    get_value_data(records_ship_owner, ship_owner_list)
# </editor-fold>
